package ckR

import (
	"crypto/md5"
	"db2s/global"
	"db2s/outPut"
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
	"sync"
)

var newCell outPut.StreamRes
var xlsFile outPut.FileOperations
var textFile outPut.FileOperations
var xlsTerminalUniq = make(map[string]int)

func tWorkSheetR(s any) (p any) {
	switch s.(type) {
	case *outPut.TPod:
		p = *(s.(*outPut.TPod))
	case outPut.TPod, outPut.SheetResultData:
		p = s
	case *outPut.SheetResultData:
		p = *(s.(*outPut.SheetResultData))
	}
	return p
}

var textSyncFunc = global.EFunc{
	FuncName: func(event string,s any) (r any) {
		var sheetName, writeStr string
		if s == nil {
			return
		}
		val := reflect.ValueOf(s)
		// 如果 s 是指针，获取指向的值
		if val.IsValid() && val.Kind() == reflect.Ptr {
			val = val.Elem()
		}
		tType := val.Type()
		var st string
		for i := 0; i < tType.NumField(); i++ {
			switch tType.Field(i).Type.Kind() {
			case reflect.Struct:
				r := tWorkSheetR(val.Field(i).Interface())
				switch r.(type) {
				case outPut.TPod:
					if q, err := json.Marshal(global.CreateNewStruct(r, append(global.GetJSONFieldNames(r.(outPut.TPod)), "Rows"))); err != nil {
						return nil
					} else {
						writeStr = fmt.Sprintf("%v\n", string(q))
					}
					st = fmt.Sprintf("%v.%v", r.(outPut.TPod).Schema, r.(outPut.TPod).Table)
				case outPut.SheetResultData:
					if q, err := json.Marshal(global.CreateNewStruct(r, append(global.GetJSONFieldNames(r.(outPut.SheetResultData)), "Rows"))); err != nil {
						return nil
					} else {
						writeStr = fmt.Sprintf("%v\n", string(q))
					}
					st = fmt.Sprintf("%v.%v", r.(outPut.SheetResultData).Schema, r.(outPut.SheetResultData).Table)
				}
			case reflect.Ptr:
				if q, err := json.Marshal(s); err != nil {
					return nil
				} else {
					writeStr = fmt.Sprintf("%v\n", string(q))
				}
			case reflect.String:
				switch tType.Field(i).Name {
				case "SheetName":
					sheetName = val.Type().Field(i).Tag.Get("json")
				}
			default:
			}
		}
		st1 := string(md5.New().Sum([]byte(fmt.Sprintf("%v%v", sheetName, st))))
		if _, ok := xlsTerminalUniq[st1]; !ok {
			if err := textFile.Write(sheetName, writeStr); err != nil {
				return nil
			}
			xlsTerminalUniq[st1]++
		}
		return
	},
}
var xlsExecFunc = global.EFunc{
	FuncName: func(event string,s any) (r any) {
		if s == nil {
			return
		}
		var sheetName string
		var writeStr []string
		switch reflect.TypeOf(s).Kind() {
		case reflect.Struct, reflect.Ptr:
			sheetName, writeStr = getXlsData(s)
		default:
		}
		if err := xlsFile.Write(sheetName, strings.Join(writeStr, outPut.CSymbol)); err != nil {
			return nil
		}
		return
	},
}

func getXlsData(s any) (sheetName string, writeStr []string) {
	val := reflect.ValueOf(s)
	// 如果 s 是指针，获取指向的值
	if val.IsValid() && val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	tType := val.Type()
	for i := 0; i < tType.NumField(); i++ {
		switch tType.Field(i).Type.Kind() {
		case reflect.Struct:
			for _, v := range outPut.RecursiveStructJsonValue(GlobalPConfigs.rules.CheckMode, val.Field(i).Interface()) {
				writeStr = append(writeStr, fmt.Sprintf("%v", v))
			}
		case reflect.Ptr:
			for _, v := range outPut.RecursiveStructJsonValue(GlobalPConfigs.rules.CheckMode, val.Field(i).Elem().Interface()) {
				writeStr = append(writeStr, fmt.Sprintf("%v", v))
			}
		case reflect.String:
			switch tType.Field(i).Name {
			case "SheetName":
				sheetName = val.Type().Field(i).Tag.Get("json")
			}
		default:
			return
		}
	}
	return
}

func Cell(wg *sync.WaitGroup) {
	var initContext = global.GetIoc().GetBean("schemaInitContext").(*SchemaInitContext)
	var sum = initContext.TableSum
	if initContext.TableSum == 0 {
		sum = 1000000
	}
	newCell = outPut.NewStreamRes(outPut.Cell{
		Wg:            wg,
		ModifyValFunc: global.EFunc{FuncName: tPodResult},
		ExecFunc:      []global.EFunc{xlsExecFunc},
		C:             make(chan any, sum),
	})
	newCell.AddFunc(textSyncFunc)
	newCell.Start()
	newCell.Run()
}
